import { App } from "../types"
import { useUserStore } from "@/store";
import { isObject } from "lodash-es"
import { libManager } from "../SeedApplication";

// 同一个库在整个应用下只能出现一次
export function checkLib(app: App) {
  const libNames = app.libs || []

  const micros = app.micros
  if(!micros) return

  for(const microName in micros) {
    const micro = micros[microName]
    if(!micro.libs) continue
    
    for(const i in micro.libs) {
      const libName = micro.libs[i]
      if(libNames.includes(libName)) throw Error(`库【${libName}】不能出现在多个服务下`)

      libNames.push(libName)
    }
  }
}

// 检查不同库下是否有相同的seedName，有则报错
export function checkLibSeedUniq(libNames: string[]) {
  libNames = libNames || []

  for(let i = 0; i < libNames.length - 1; i ++) {
    const libName = libNames[i]
    const lib = libManager.getLib(libName)

    const seedNames = Object.keys(lib.seeds || {})
    for(let j = i + 1; j < libNames.length; j ++) {
      const otherLibName = libNames[j]
      const otherLib = libManager.getLib(otherLibName)

      const otherSeeds = otherLib.seeds || {}
      for(const seedName in otherSeeds) {
        if(seedNames.includes(seedName)) {
          throw Error(`库【${libName}】和库【${otherLibName}】具有相同的元数据【${seedName}】,不能同时引用`)
        }
      }
    }
  }
}

// export function findSeed(app: App, seedName: string, microName?: string) {
//   if(microName) {
//     if(!app.micros) throw Error(`应用下没有任何服务`)
    
//     const micro = app.micros[microName]
//     if(!micro) throw Error(`服务【${microName}】不存在`)

//     const seeds = micro.seeds
//     if(!seeds) throw Error(`服务【${microName}】下没有任何元数据`)

//     const seed = seeds[seedName]
//     if(!seed) throw Error(`服务【${microName}】下没有【${seedName}】`)

//     return seed
//   }

//   const seeds = app.seeds
//   if(!seeds) throw Error(`应用下没有任何元数据`)

//   const seed = seeds[seedName]
//   if(!seed) throw Error(`应用下没有【${seedName}】`)

//   return seed
// }

// export function getMicroMenus(...positions: SeedPosition[]) {
//   const ret: MenuItem[] = []
//   const userStore = useUserStore()
//   if(!userStore.isLogin) return ret

//   const allModules = hasModules(userStore.permissions)

//   const routes = router.getRoutes()
//   const tops = routes.filter(e => !e.name && e.path === '/' && e.meta?.hidden !== true)
//   console.log('tops===', tops)
//   const roots = []
//   if(tops && tops.length > 0) {
//     const top = tops[0]
//     for(const child of top.children) roots.push(child)
//   }

//   const rootNames = roots.map(e => e.name)
//   const micros = routes.filter(e => e.name && !rootNames.includes(e.name) && !e.path.substring(1).includes('/') && e.meta?.hidden !== true)
//   for(const root of roots) {
//     if(root.meta?.hidden === true || !hasModule(allModules, root.name as string)) continue

//     const position = root.meta?.position || 'menu'
//     const seedPositions = isArray(position) ? position as SeedPosition[] : [position as SeedPosition]
//     if(seedPositions.some(e => positions.includes(e))) {
//       ret.push({
//         name: root.name,
//         label: root.meta?.label,
//         icon: root.meta?.icon,
//         path: `/${root.path}`,
//         mode: root.meta?.mode,
//         component: root.component,
//         componentProps: root.props
//       })
//     }
//   }
  
//   for(const micro of micros) {
//     const children = []
//     const microName = micro.name as string
//     for(const child of micro.children) {
//       if(child.meta?.hidden === true || !hasModule(allModules, child.name as string)) continue

//       const position = child.meta?.position || 'menu'
//       const seedPositions = isArray(position) ? position as SeedPosition[] : [position as SeedPosition]
//       if(seedPositions.some(e => positions.includes(e))) {
//         children.push({
//           name: `${microName}/${child.name as string}`,
//           label: child.meta?.label as string,
//           icon: child.meta?.icon as string,
//           path: `/${microName}/${child.path}`,
//           mode: child.meta?.mode,
//           component: child.component,
//           componentProps: child.props
//         })
//       }
//     }
//     if(children.length > 0) {
//       ret.push({
//         name: microName,
//         label: micro.meta?.label as string,
//         icon: micro.meta?.icon as string,
//         path: micro.path,
//         children
//       })
//     }
//   }

//   console.log('menus', ret)

//   return ret
// }

export function hasModule(allModules: boolean | Record<string, string[]>, name: string, microName?: string) {
  if(isObject(allModules)) {
    const modules = allModules as Record<string, string[]>
    microName = microName || ''
    const seedNames = modules[microName] || []
    return seedNames.includes(name)
  }

  return allModules as boolean
}

export function hasModules(permissions: string[]) {
  if(!permissions || permissions.length == 0) return false
  if(permissions.includes('*')) return true

  const items = []
  for(const item of permissions) items.push(item.substring(0, item.lastIndexOf('.')))

  const ret: Record<string, string[]> = {}
  for(const item of items) {
    const microAndModule = item.split('.')
    if(microAndModule.length == 1) {
      const value = ret[''] || []
      if(!value.includes(item)) value.push(item)
      ret[''] = value
    } else {
      const [microName, seedName] = microAndModule
      const value = ret[microName] || []
      if(!value.includes(seedName)) value.push(seedName)
      ret[microName] = value
    }
  }

  return ret
}

// export function getRoutes(app: App) {
//   const ret: RouteRecordRaw[] = [
//     {
//       name: 'login',
//       path: '/login',
//       component: app.loginLayout ? Container : getComponent('login', app.login),
//       props: app.loginLayout ? { layout: app.loginLayout, props: app.loginProps } : app.loginProps,
//       meta: {
//         affix: false,
//         hidden: true,
//         breadcrumb: false,
//         noTagsView: true,
//         label: '用户登录'
//       }
//     },
//     {
//       path: '/',
//       component: app.layout ? Container : getComponent('layout', app.component),
//       props: app.layout ? { layout: app.layout, props: app.componentProps } : app.componentProps,
//       children: [
//         {
//           name: '/',
//           path: '',
//           component: app.homeLayout ? Container : getComponent('home', app.home),
//           props: app.homeLayout ? { layout: app.homeLayout, props: app.homeProps } : app.homeProps,
//           meta: {
//             affix: true,
//             hidden: true,
//             breadcrumb: false,
//             noTagsView: false,
//             label: `首页`,
//             icon: 'bxs:home'
//           }
//         },
//         ...actionToRoutes(app.actions),
//         ...homeToRoutes(app.homes),
//         ...seedToRoutes(app.seeds)
//       ]
//     },
//     {
//       name: 'NoFind',
//       path: '/404',
//       component: app.errorLayout ? Container : getComponent('error', app.error),
//       props: app.errorLayout ? { layout: app.errorLayout, props: app.errorProps } : app.errorProps,
//       meta: {
//         affix: false,
//         hidden: true,
//         breadcrumb: false,
//         noTagsView: true,
//         title: '404'
//       }
//     },
//     {
//       name: 'Redirect',
//       path: '/redirect/:path(.*)',
//       component: app.redirectLayout ? Container : getComponent('redirect', app.redirect),
//       props: app.redirectLayout ? { layout: app.redirectLayout, props: app.redirectProps } : app.redirectProps,
//       meta: {
//         affix: false,
//         hidden: true,
//         breadcrumb: false,
//         noTagsView: true
//       }
//     }
//   ]

//   const micros = app.micros
//   if(!micros) return ret

//   for(const microName in micros) {
//     const micro = micros[microName]
//     ret.push({
//       name: microName,
//       path: `/${microName}`,
//       component: micro.layout ? Container : getComponent('layout', micro.component),
//       props: micro.layout ? { layout: micro.layout, props: micro.componentProps } : micro.componentProps,
//       meta: {
//         affix: false,
//         hidden: false,
//         breadcrumb: true,
//         noTagsView: false,
//         label: micro.label,
//         icon: micro.icon
//       },
//       children: [ ...actionToRoutes(micro.actions, micro), ...homeToRoutes(micro.actions, micro), ...seedToRoutes(micro.seeds, micro) ]
//     })
//   }

//   return ret
// }

// export function homeToRoutes(homes: Record<string, Home>, micro?: Micro) {
//   const ret: RouteRecordRaw[] = []
//   if(!homes) return ret

//   const names = ['login', 'Redirect', 'NoFind', '404', '/', '404Page']
//   for(const name in homes) {
//     if(names.includes(name)) throw Error(`首页名称不能是【${name}】`)

//     const home = homes[name]
//     const { component, layout, componentProps, affix, hidden, breadcrumb, noTagsView, position, label, icon } = home
//     ret.push({
//       name: micro ? `${micro.name}/${name}` : name,
//       path: name,
//       component: layout ? Container : getComponent('home', component),
//       props: layout ? { layout, props: componentProps } : componentProps,
//       meta: {
//         affix: affix == undefined ? false : affix,
//         hidden: hidden == undefined ? false : hidden,
//         breadcrumb: breadcrumb == undefined ? true : breadcrumb,
//         noTagsView: noTagsView == undefined ? false : noTagsView,
//         position: position || 'menu',
//         mode: home.mode,
//         label: label || `首页`,
//         icon: icon || 'bxs:home'
//       }
//     })
//   }

//   return ret
// }

// export function actionToRoutes(actions: Record<string, Action>, micro?: Micro) {
//   const ret: RouteRecordRaw[] = []
//   if(!actions) return ret

//   for(const name in actions) {
//     const action = actions[name]
//     const { component, layout, componentProps, position, label, icon } = action
//     const props = { ...(componentProps || {}), action }
//     ret.push({
//       name: micro ? `${micro.name}/${name}` : name,
//       path: name,    
//       component: layout ? Container : getComponent(action.type, component),
//       props: layout ? { layout, props } : props,
//       meta: {
//         affix: false,
//         hidden: false,
//         breadcrumb: true,
//         noTagsView: false,
//         position: position || 'menu',
//         mode: action.mode,
//         label: label || name,
//         icon: icon || 'bxs:setting'
//       }
//     })
//   }

//   return ret
// }

export function getActions(app: App) {
  const ret = []

  const userStore = useUserStore()
  const actions = app.actions || {}
  for(const actionName in actions) {
    const action = actions[actionName]
    const value = `.${action.name}`
    if(userStore.assignable(value)) {
      // ret.push({permission, value: {action: action.name}, label: action.label || action.name})
      ret.push({value, label: action.label || action.name})
    }
  }

  for(const seedName in app.seeds) {
    const seed = app.seeds[seedName]
    const children = []
    for(const actionName in seed.actions) {
      const action = seed.actions[actionName]
      const value = `.${seedName}.${action.name}`
      if(userStore.assignable(value)) {
        // children.push({permission, value: {module: seedName, action: action.name}, label: action.label || action.name})
        children.push({value, label: action.label || action.name})
      }
    }
    if(children.length > 0) ret.push({label: `${seed.label}管理`, children})
  }

  if(!app.micros) return ret

  for(const microName in app.micros) {
    const micro = app.micros[microName]
    const modules = []
    const actions = micro.actions || {}
    for(const actionName in actions) {
      const action = actions[actionName]
      const value = `${microName}.${action.name}`
      if(userStore.assignable(value)) {
        modules.push({value, label: action.label || action.name})
      }
    }

    for(const seedName in micro.seeds) {
      const seed = micro.seeds[seedName]
      const children = []
      for(const actionName in seed.actions) {
        const action = seed.actions[actionName]
        const value = `${microName}.${seedName}.${action.name}`
        if(userStore.assignable(value)) {
          children.push({value, label: action.label || action.name})
        }
      }
      if(children.length > 0) modules.push({label: `${seed.label}管理`, children})
    }

    if(modules.length > 0) ret.push({label: micro.label || microName, children: modules })
  }
    
  return ret
}

export function getDataActions(app: App) {
  const ret = []

  const actions = app.actions || {}
  for(const actionName in actions) {
    const action = actions[actionName]
    const value = `.${action.name}`
    ret.push({action, value, label: action.label || action.name})
  }

  for(const seedName in app.seeds) {
    const seed = app.seeds[seedName]
    const children = []
    for(const actionName in seed.actions) {
      const action = seed.actions[actionName]
      children.push({action, value: `.${seedName}.${action.name}`, label: action.label || action.name})
    }
    if(children.length > 0) ret.push({label: `${seed.label}管理`, children})
  }

  if(!app.micros) return ret

  for(const microName in app.micros) {
    const micro = app.micros[microName]
    const modules = []
    const actions = micro.actions || {}
    for(const actionName in actions) {
      const action = actions[actionName]
      const value = `${microName}.${action.name}`
      modules.push({action, value, label: action.label || action.name})
    }

    for(const seedName in micro.seeds) {
      const seed = micro.seeds[seedName]
      const children = []
      for(const actionName in seed.actions) {
        const action = seed.actions[actionName]
        children.push({action, value: `${microName}.${seedName}.${action.name}`, label: action.label || action.name})
      }
      if(children.length > 0) modules.push({label: `${seed.label}管理`, children})
    }

    if(modules.length > 0) ret.push({label: micro.label || microName, children: modules })
  }
    
  return ret
}

export function getFieldActions(app: App) {
  const ret = []

  const actions = app.actions || {}
  for(const actionName in actions) {
    const action = actions[actionName]
    const value = `.${action.name}`
    ret.push({action, value, label: action.label || action.name})
  }

  for(const seedName in app.seeds) {
    const seed = app.seeds[seedName]
    const children = []
    for(const actionName in seed.actions) {
      const action = seed.actions[actionName]
      children.push({action, value: `.${seedName}.${action.name}`, label: action.label || action.name})
    }
    if(children.length > 0) ret.push({label: `${seed.label}管理`, children})
  }

  if(!app.micros) return ret

  for(const microName in app.micros) {
    const micro = app.micros[microName]
    const modules = []
    const actions = micro.actions || {}
    for(const actionName in actions) {
      const action = actions[actionName]
      const value = `${microName}.${action.name}`
      modules.push({action, value, label: action.label || action.name})
    }

    for(const seedName in micro.seeds) {
      const seed = micro.seeds[seedName]
      const children = []
      for(const actionName in seed.actions) {
        const action = seed.actions[actionName]
        children.push({action, value: `${microName}.${seedName}.${action.name}`, label: action.label || action.name})
      }
      if(children.length > 0) modules.push({label: `${seed.label}管理`, children})
    }

    if(modules.length > 0) ret.push({label: micro.label || microName, children: modules })
  }
    
  return ret
}

export function permissionsToTree(app: App, permissions: string[]) {
  if(!permissions || permissions.length == 0) return []

  const micros: Record<string, Record<string, string[]>> = {}
  for(const permission of permissions) {
    const items = permission.split('.')
    const len = items.length
    if(len < 2 || len > 3) continue

    const hasMicro = len == 3
    const microName = hasMicro ? items[0] : ''
    const seedName = items[hasMicro ? 1 : 0]
    const actionName = items[hasMicro ? 2 : 1]
    const micro = micros[microName] || {}
    const actionNames = micro[seedName] || []
    actionNames.push(actionName)
    micro[seedName] = actionNames
    micros[microName] = micro
  }
  console.log('micros===', micros)

  const ret = []
  for(const microName in micros) {
    const tmpMicro = micros[microName]
    if(microName) {
      const micro = app.micros[microName]
      const seeds = []
      for(const seedName in tmpMicro) {
        const seed = micro.seeds[seedName]
        const actionNames = tmpMicro[seedName]
        const actions = actionNames.map(e => ({value: e, label: seed.actions[e].label}))
        seeds.push({value: seedName, label: seed?.label || seedName, children: actions})
      }
      ret.push({value: microName, label: micro?.label || microName, type: 'micro', children: seeds})
    } else {
      for(const seedName in tmpMicro) {
        const seed = app.seeds[seedName]
        const actionNames = tmpMicro[seedName]
        const actions = actionNames.map(e => ({value: e, label: seed.actions[e]?.label || e}))
        ret.push({value: seedName, label: seed?.label || seedName, type: 'app', children: actions})
      }
    }
  }

  console.log('ret----', ret)
  return ret
}
